/*
 * Copyright 2008 Jens Meiss
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package mtt.calendar;

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import mtt.rms.recordstores.calendar.Week;

/**
 *
 *
 * @author jens.meiss
 */
public class CalenderWeekGenerator {
	
	/**
	 * @deprecated Use {@link Week#millisOfASecond} instead
	 * 
	 */
	public static final int millisOfASecond = Week.millisOfASecond;
	
	/**
	 * @deprecated Use {@link Week#millisOfAMinute} instead
	 *
	 */
	public static final int millisOfAMinute = Week.millisOfAMinute; /* 60 * 1000 = 60000 */
	
	/**
	 * @deprecated Use {@link Week#millisOfAHour} instead
	 * 
	 */
	public static final int millisOfAHour = Week.millisOfAHour;	/* 60 * 60000 = 3600000 */
	
	/**
	 * contains the count of Milliseconds of a Day
	 * @deprecated Use {@link Week#millisOfADay} instead
	 */
	public static final long millisOfADay = Week.millisOfADay; 	/* 1000 * 60 * 60 * 24  = 86400000*/
	
	public static void configureCurrentWeek(Week week) {
		
		setDateOfFirstAndLastDayOfWeek(new Date(), week);
		setWeekNumber(week);
		
	}
	
	/**
	 * setzt das Date des ersten und des letzten Tags der Woche
	 * 
	 * @param Date
	 *            für welches der erste und letzte Tag der Woche gesetzt werden
	 *            soll
	 * @param Week
	 *            in die die Date Objekt eingetragen werden soll
	 */
	private static void setDateOfFirstAndLastDayOfWeek(Date date, Week week) {

		Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
		calendar.setTime(date);		
		
		/*
		 * Date auf 00:00:00 Uhr des Tages setzen
		 */
		long time = date.getTime();
		time -= calendar.get(Calendar.MILLISECOND);
		time -= calendar.get(Calendar.SECOND) * Week.millisOfASecond;
		time -= calendar.get(Calendar.MINUTE) * Week.millisOfAMinute;
		time -= calendar.get(Calendar.HOUR_OF_DAY) * Week.millisOfAHour;
		
		date = new Date(time);
		
		
		Calendar calendar2 = Calendar.getInstance(TimeZone.getDefault());
		calendar2.setTime(date);

		/*
		 * zum ersten Tag der Woche zurück rechnen
		 */

		/*
		 * DAY_OF_WEEK des aktuellen Tags
		 */
		int dayOfWeek = calendar2.get(Calendar.DAY_OF_WEEK);

		switch (dayOfWeek) {
		case 1: 
			dayOfWeek = 7;
			break;
		case 2: 
			dayOfWeek = 1;
			break;
		case 3: 
			dayOfWeek = 2;
			break;
		case 4: 
			dayOfWeek = 3;
			break;
		case 5: 
			dayOfWeek = 4;
			break;
		case 6: 
			dayOfWeek = 5;
			break;
		case 7: 
			dayOfWeek = 6;
			break;
			
		}

		/*
		 * wieviele Tage liegen zwischen dem ersten und dem aktuellen Tag der
		 * Woche
		 */
		int diffDays = dayOfWeek - 1;

		/*
		 * zum Zeitpunkt des ersten Tags der Woche zurück rechnen
		 */
		long millisOfFirstDayOfWeek = date.getTime()
				- (diffDays * Week.millisOfADay);
		
		Date dateFirstDayOfWeek = new Date(millisOfFirstDayOfWeek);

		/*
		 * ersten Tag der Woche im Week-Objekt setzen
		 */
		week.setDateFirstDayOfWeek(dateFirstDayOfWeek);

		/*
		 * letzten Tag der Woche ermitteln
		 */
		long millisOfLastDayOfWeek = millisOfFirstDayOfWeek
				+ (Week.millisOfAWeek  - 1);
		Date dateLastDayOfWeek = new Date(millisOfLastDayOfWeek);

		/*
		 * letzten Tag der Woche im Week-Objekt setzen
		 */
		week.setDateLastDayOfWeek(dateLastDayOfWeek);
	}
	
	/**
	 * setzt die Nummer der Woche (1-52)
	 * 
	 * @param Date-Objekt
	 *            für welches die weekNumber errechnet werden soll
	 * @param Week-Objekt
	 *            welches die die weekNumber erhalten soll
	 */
	private static void setWeekNumber(Week week) {
		/*
		 * Calendar des Date-Objekts erzeugen
		 */
		Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
		calendar.setTime(week.getDateFirstDayOfWeek());

		/*
		 * Kalender des 01.01. des aktuellen Jahres erstellen
		 */
		Calendar calendarFirstDayOfYear = Calendar.getInstance(TimeZone
				.getDefault());

		calendarFirstDayOfYear.set(Calendar.DAY_OF_MONTH, 1);
		calendarFirstDayOfYear.set(Calendar.MONTH, Calendar.JANUARY);

		calendarFirstDayOfYear.set(Calendar.HOUR_OF_DAY, 0);
		calendarFirstDayOfYear.set(Calendar.MINUTE, 0);
		calendarFirstDayOfYear.set(Calendar.SECOND, 0);
		calendarFirstDayOfYear.set(Calendar.MILLISECOND, 0);

		/*
		 * Jahr des Date-Objekts eintragen
		 */
		calendarFirstDayOfYear.set(Calendar.YEAR, calendar.get(Calendar.YEAR));

		/*
		 * Datum des 01.01. des aktuellen Jahres ermitteln
		 */
		Date dateFirstDayOfYear = calendarFirstDayOfYear.getTime();

		/*
		 * Der erste Tag der Woche ist Montag, der erste Tag des Jahres meistens
		 * nicht, die erste Woche des Jahres fängt am Montag in der Woche mit
		 * dem ersten Tag des Jahres an, also muss vom 01.01 des Jahres noch zum
		 * ersten Tag der Woche zurück gerechnet werden, da sonst jede Woche an
		 * dem Tag anfängt an dem der erste Tag des Jahres war
		 */

		/*
		 * Time des ersten Tags des Jahres - der Zeit die seit dem Tag in der
		 * Woche vergangen ist (zum ersten Tag der Woche springen)
		 * 
		 * -2 weil im j2me Calender die Woche am Sonntag beginnt, nicht am
		 * Montag
		 */
		long longTimeOfFirstDayOfFirstWeek = dateFirstDayOfYear.getTime()
				- ((calendarFirstDayOfYear.get(Calendar.DAY_OF_WEEK) - 2) * Week.millisOfADay);

		/*
		 * anzahl der Wochen die seit dem ersten Tag der ersten Woche vergangen
		 * sind, ermitteln
		 */
		long weekCount = (new Date().getTime() - longTimeOfFirstDayOfFirstWeek)
				/ (1000 * 60 * 60 * 24 * 7);

		/*
		 * cast longWeekNumber to byte
		 */
		long longWeekNumber = weekCount + 1;
		
		/*
		 * valid weeknumber?
		 */
		if ((longWeekNumber <= 52) && (longWeekNumber >= 1)) {
			/*
			 * set weekNumber
			 */
			week.setWeekNumber((byte) longWeekNumber);
			
		} else {
			/*
			 * not a valid weekNumber (1-52)
			 */
			throw new NullPointerException("Invalid longWeekNumber, can't cast (long)" + longWeekNumber + " into valid weekNumber (1-52)");
		}
	}

}
